package com.wsyu.springbootbackend.config;

import com.wsyu.springbootbackend.core.auth.config.AbstractCustomSecurityConfig;
import com.wsyu.springbootbackend.core.auth.filter.CustomJwtFilter;
import com.wsyu.springbootbackend.core.auth.filter.CustomUsernamePasswordAuthenticationFilter;
import com.wsyu.springbootbackend.core.auth.handler.CustomAccessDeniedHandler;
import com.wsyu.springbootbackend.core.auth.handler.CustomAuthenticationEntryPoint;
import com.wsyu.springbootbackend.core.auth.handler.CustomAuthenticationFailureHandler;
import com.wsyu.springbootbackend.core.auth.handler.CustomAuthenticationSuccessHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@RequiredArgsConstructor
@EnableWebSecurity(debug = false)
public class SecurityConfig {

    @Bean
    public AuthenticationSuccessHandler authenticationSuccessHandler() {
        return new CustomAuthenticationSuccessHandler();
    }

    @Bean
    public AuthenticationFailureHandler authenticationFailureHandler() {
        return new CustomAuthenticationFailureHandler();
    }

    @Bean
    public AuthenticationEntryPoint authenticationEntryPoint() {
        return new CustomAuthenticationEntryPoint();
    }

    @Bean
    public AccessDeniedHandler accessDeniedHandler() {
        return new CustomAccessDeniedHandler();
    }

    @Bean
    public CustomJwtFilter jwtFilter() {
        return new CustomJwtFilter();
    }

    @Bean
    public CustomUsernamePasswordAuthenticationFilter customUsernamePasswordAuthenticationFilter(AuthenticationManager authenticationManager) {
        return new CustomUsernamePasswordAuthenticationFilter(authenticationManager);
    }

    @Bean
    @SuppressWarnings("deprecation")
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

    // 注入AuthenticationManager
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
        return authConfig.getAuthenticationManager();
    }


    // 配置安全过滤器链
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http,
                                           CustomUsernamePasswordAuthenticationFilter customFilter,
                                           CustomJwtFilter jwtFilter) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()        // 没有任何权限要求，甚至，也没有“登录”要求
                .anyRequest().authenticated(); // 2

        http.exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint())
                .accessDeniedHandler(accessDeniedHandler());

        http.formLogin()
                .successHandler(authenticationSuccessHandler())
                .failureHandler(authenticationFailureHandler());

//        http.addFilterAt(customFilter, UsernamePasswordAuthenticationFilter.class);
        http.addFilterAfter(jwtFilter, UsernamePasswordAuthenticationFilter.class);

        http.httpBasic().disable() // 和表单登录功能“互斥”，没用上；
                .formLogin().disable()
                .csrf().disable();      // 安全性设置，一般会关掉它；

        http.sessionManagement()    // 前后端分离项目声明
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        return http.build();
    }
    // endregion


    @Bean
    public UserDetailsService userDetailsService() {
        // 创建两个测试用户
        UserDetails user1 = User.withUsername("user")
                .password("password")
                .roles("USER")
                .build();

        UserDetails admin = User.withUsername("admin")
                .password("admin123")
                .roles("ADMIN", "USER")
                .build();

        return new InMemoryUserDetailsManager(user1, admin);
    }
    // endregion
}
